package org.icop.frame.boost;

import org.icop.model.MultiSet;
import org.icop.model.ValuedCorrespondence;
import org.jbpt.graph.abs.IEdge;
import org.jbpt.graph.abs.IGraph;
import org.jbpt.hypergraph.abs.IVertex;


/**
 * We boost matches that subsume other matches. The idea behind
 * is that big (in terms of the size of the matched node sets)
 * matches tend to have a lower sim score than small matches due 
 * to the preferences of the VSM model. This booster counteracts
 * by boosting the sim scores of the big matches.
 * 
 * Note that we do nothing for matches that have equivalent node
 * sets.
 * 
 * @author matthias.weidlich
 *
 */
public class MatchSubsumptionBooster<G extends IGraph<E,V>, E extends IEdge<V>, V extends IVertex> implements Booster<G, E, V> {

	public static double boostFactor;
	
	public MatchSubsumptionBooster() {
		this(0.5);
	}
	
	public MatchSubsumptionBooster(double boostFactor) {
		MatchSubsumptionBooster.boostFactor = boostFactor;
	}
	
	@Override
	public MultiSet<ValuedCorrespondence<V>> boost(G sg1, G sg2,
			MultiSet<ValuedCorrespondence<V>> mapping) {

		/*
		 * Determine the subsumption between the matches
		 */
		for (ValuedCorrespondence<V> sets1 : mapping) {
			for (ValuedCorrespondence<V> sets2 : mapping) {
				if (subsumesMatch(sets1,sets2)) {
					sets1.setConfidenceValue(boostedSimScore(sets1.getConfidenceValue(),sets2.getConfidenceValue()));
				}
			}
		}
		
		return mapping;
	}
	
	protected boolean subsumesMatch(ValuedCorrespondence<V> subsumer, ValuedCorrespondence<V> subsumed) {
		return subsumer.getV1s().containsAll(subsumed.getV1s()) 
			&& subsumer.getV2s().containsAll(subsumed.getV2s()) 
			&& (!subsumer.getV1s().equals(subsumed.getV1s())
					|| !subsumer.getV2s().equals(subsumed.getV2s()));
	}
	
	protected double boostedSimScore(double baseScore, double boostScore) {
		double diff = 1 - baseScore;
		double boost = boostFactor * diff * boostScore;
		return baseScore + boost;
	}


}
